package net.schst.XJConf;

import java.lang.reflect.Constructor;

import net.schst.XJConf.exceptions.ValueConversionException;

/**
 * Class to convert a value to an object
 * 
 * @author Stephan Schmidt <stephan.schmidt@schlund.de>
 */
public class ObjectValueConverter implements ValueConverter {

    /**
     * Name of the target class
     */
    private String className;
    
    /**
     * Create a new converter
     * 
     * @param className
     */
    public ObjectValueConverter(String className) {
        this.className = className;
    }
    
    /**
     * Convert the value
     * 
     * @param values    Values for the constructor
     * @param types     Types of the values
     * @param loader    classloader to use
     */
    public Object convertValue(Object[] values, Class[] types, ClassLoader loader)
        throws ValueConversionException {
        Class instanceClass;
        Object instance;
        
        // try to get the class object
        try {
            instanceClass = Class.forName(this.className,true,loader);
        } catch (Exception e) {
            throw new ValueConversionException("Class " + this.className + " does not exist", e);
        }
        // try to create a new instance
        try {
        	Constructor co;
        	try {
        		co = instanceClass.getConstructor(types);
        	} catch (NoSuchMethodException e) {
        		// try to convert the values to a string
        		for (int i = 0; i < types.length; i++) {
        			types[i]  = String.class;
        			values[i] = values[0].toString();
        		}
        		co = instanceClass.getConstructor(types);        		
        	}
            instance = co.newInstance(values);
        } catch (Exception e){
            try {
                // no matching constructor has been found
                // try to instantiate the class without using
                // a constructor
                instance = instanceClass.newInstance();
            } catch (Exception e2) {
                throw new ValueConversionException("Could not create instance of " + this.className, e2);
            }
        }
        return instance;
    }
    
    /**    
     * Get the type of the returned value
     * 
     * @return    Class object
     */
    public Class getType(ClassLoader loader) throws Exception {
        return Class.forName(this.className, true, loader);
    }
}
